﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Routing;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the resource string builder.
    /// </summary>
    public sealed class Res : SChain
    {
        #region Ctors

        private Res(string pack) 
            : base(pack + ':')
        {
        }

        #endregion

        #region Methods

        public static Res In(string pack)
        {
            return new Res(pack);
        }

        public Res Of(string section)
        {
            return Section(section);
        }

        public Res Of(Type t)
        {
            return Of(t.Name);
        }

        public Res Of<T>()
        {
            return Of(typeof(T));
        }

        public Res Of(object obj)
        {
            return Of(obj.GetType());
        }

        public Res Section(object section)
        {
            Builder.Append(section)
                .Append('.');
            return this;
        }

        public Res Name(object key)
        {
            Builder.Append(key);
            return this;
        }

        #endregion
    }

    public class Loc : ICloneable
    {
        #region Fields

        private readonly RouteValueDictionary _params;

        #endregion

        #region Ctors

        protected Loc()
        {
            _params = new RouteValueDictionary();
        }

        #endregion

        #region Properties

        internal string Action
        {
            get;
            private set;
        }

        internal string Controller
        {
            get;
            private set;
        }

        internal string Protocol
        {
            get;
            private set;
        }

        internal string Host
        {
            get;
            private set;
        }

        internal RouteValueDictionary Params
        {
            get
            {
                return _params;
            }
        }

        #endregion

        #region Methods

        public static Loc Act(string action)
        {
            return new Loc
            {
                Action = action
            };
        }

        public Loc Ctrl(string controller)
        {
            Controller = controller;
            return this;
        }

        public Loc Area(string area)
        {
            return Set("area", area);
        }

        public Loc NoArea()
        {
            return Area(String.Empty);
        }

        public Loc Proto(string protocol)
        {
            Protocol = protocol;
            return this;
        }

        public Loc Hst(string host)
        {
            Host = host;
            return this;
        }

        public Loc Set(object values)
        {
            Params.AddValues(values);
            return this;
        }

        public Loc Set(IDictionary<String, Object> values)
        {
            Params.AddValues(values);
            return this;
        }

        public Loc Set(string key, object val)
        {
            Params[key] = val;
            return this;
        }

        public Loc Rst(params string[] keys)
        {
            if(keys != null)
            {
                foreach(var key in keys)
                    Rst(key);
            }
            return this;
        }

        public Loc Rst(string key)
        {
            if(Params.ContainsKey(key))
                Params.Remove(key);
            return this;
        }

        public Loc Use(params string[] keys)
        {
            if(keys != null)
            {
                foreach(var key in keys)
                    Use(key);
            }
            return this;
        }

        public Loc Use(string key)
        {
            if(HttpContext.Current == null)
                return this;
            var httpCtx = HttpContext.Current;
            var req = httpCtx.Request;
            var reqCtx = req.RequestContext;
            Set(key, reqCtx.RouteData.Values.ContainsKey(key) 
                ? reqCtx.RouteData.Values[key] 
                : req.Params[key]);
            return this;
        }

        public Loc Copy()
        {
            return Clone() as Loc;
        }

        public object Clone()
        {
            return new Loc
            {
                Action = Action,
                Controller = Controller,
                Host = Host,
                Protocol = Protocol
            }.Set(Params);
        }

        #endregion
    }
}
